﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
//using System.Windows;
using System.Windows.Forms;
using System.Drawing.Imaging;

namespace LetiLib.Utils
{
    public abstract class ObjectRender
    {
        protected Size _pixelResolution
        {
            get { return new Size(mXPixels, mYPixels); }
            set
            {
                mXPixels = (ushort)value.Width;
                mYPixels = (ushort)value.Height;
            }
        }

        protected int mXPixels = 128;// real led width's pixel
        protected int mYPixels = 64;// real led height's pixel

        protected int mPixelGapX = 0;// gap between pixels in vertical
        protected int mPixelGapY = 0;// gap between pixels in horizontal
        
        #region | blink |
        private bool blinking = true;
        private bool blinkingFlag = false;
        private System.Timers.Timer tmBlink;
        public bool Blinking
        {
            get { return blinking; }
            set
            {
                blinking = value;
                if (blinking == true)
                {
                    if (tmBlink == null)
                    {
                        tmBlink = new System.Timers.Timer(250);
                        tmBlink.Elapsed += new System.Timers.ElapsedEventHandler(tmBlink_Elapsed);
                    }
                    tmBlink.AutoReset = true;
                    tmBlink.Start();
                    blinkingFlag = true;
                }
                else
                {
                    tmBlink.AutoReset = false;
                    tmBlink.Stop();
                    blinkingFlag = true;
                }

            }
        }

        /// <summary>
        /// Event to blink bad led
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <returns></returns>
        void tmBlink_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (blinking == false)
            {
                tmBlink.Stop();
                tmBlink.AutoReset = false;
            }
            else
            {
                blinkingFlag = !blinkingFlag;
            }
        }

        #endregion

        protected Bitmap _sourceBitmap = null;
        protected UserControl _target = null;
        //protected Rectangle _drawRect;
        protected bool _scaled = false;
        protected Graphics _graphic;
        public void Render(Bitmap source, UserControl target,Graphics g,Size pixelResolution, bool scaled)
        {
            _sourceBitmap = source;
            _target = target;
            //_drawRect = drawRect;
            _pixelResolution = pixelResolution;
            _scaled = scaled;
            _graphic = g;
            RenderImpl();
        }

        abstract protected void RenderImpl();
        
    }

    public class TriLedColorObjectRender : ObjectRender
    {

        private byte[] BitmapToByteArray2(Bitmap bmp)
        {
            // Lock the bitmap's bits.  
            Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
            System.Drawing.Imaging.BitmapData bmpData =
                bmp.LockBits(rect, ImageLockMode.ReadOnly,
                bmp.PixelFormat);

            int absStride = Math.Abs(bmpData.Stride);
            int bytes = absStride * bmp.Height;

            // Declare an array to hold the bytes of the bitmap.
            byte[] rgbValues = new byte[bytes];

            for (int i = 0; i < bmp.Height; i++)
            {
                IntPtr pointer = new IntPtr(bmpData.Scan0.ToInt32() + (bmpData.Stride * i));

                System.Runtime.InteropServices.Marshal.Copy(pointer, rgbValues, absStride * (bmp.Height - i - 1), absStride);
            }

            // Unlock the bits.
            bmp.UnlockBits(bmpData);

            return rgbValues;
        }

        protected override void RenderImpl()
        {
            int _pixelSize = ImageUtils.GetPixelSize(_sourceBitmap.PixelFormat);
            // we support 24bpp bitmap only
            if (_pixelSize != 3 ) return;

            int Width = _target.Width;
            int Height = _target.Height;
            Padding Margin = _target.Margin;

            int ledWidth = _pixelResolution.Width > 0 ? Width / _pixelResolution.Width : 0;
            int ledHeight = _pixelResolution.Height > 0 ? Height / _pixelResolution.Height : 0;

            float fScaleRatioX = _pixelResolution.Width;
            float fScaleRatioY = _pixelResolution.Height;
            float posX = 0;
            float posY = 0;
            //int itemWidth = mLedItemMatrix.GetLength(0);
            //int itemHeight = mLedItemMatrix.GetLength(1);

            //_graphic.DrawString("test",new Font("Arial",10),Brushes.Aqua,new Point(20,20));

            if (_scaled)
                _sourceBitmap = (Bitmap)ImageUtils.ResizeImage(_sourceBitmap, ledWidth, ledHeight);
            Color _currentColor;
            for (int y = 0; y < ledHeight; y++)
            {
                posY = (float)(fScaleRatioY * y);
                for (int x = 0; x < ledWidth; x++)
                {
                    posX = (float)(fScaleRatioX * (x));
                    if (x >=0 && x < _sourceBitmap.Width && 
                        y >=0 && y < _sourceBitmap.Height)
                    {

                        // BGRA bitmap -> RGBA Color
                        _currentColor = _sourceBitmap.GetPixel(x,y);
                        if (_currentColor.ToArgb() == Color.Red.ToArgb() ||
                            _currentColor.ToArgb() == Color.Lime.ToArgb() ||
                            _currentColor.ToArgb() == Color.Yellow.ToArgb())
                        {
                            _graphic.FillEllipse(new SolidBrush(_currentColor), posX, posY, fScaleRatioX, fScaleRatioY);
                        }
                        else
                        {
                            _graphic.FillEllipse(new SolidBrush(Color.Transparent), posX, posY, fScaleRatioX, fScaleRatioY);
                        }

                    }
                    else
                    {
                        _graphic.FillEllipse(new SolidBrush(Color.Transparent), posX, posY, fScaleRatioX, fScaleRatioY);
                    }

                }
            }

            /*
            // Get bitmap data
            BitmapData _bmd = _sourceBitmap.LockBits(
                                    new Rectangle(0, 0, _sourceBitmap.Width, _sourceBitmap.Height), 
                                    ImageLockMode.ReadWrite,
                                    _sourceBitmap.PixelFormat);
            unsafe
            {
                byte* _current = (byte*)(void*)_bmd.Scan0;
                int _nWidth = _sourceBitmap.Width * _pixelSize;
                int _nHeight = _sourceBitmap.Height;

               
                for (int y = 0; y < ledHeight; y++)
                {
                    posY = (float)(fScaleRatioY * y );
                    for (int x = 0; x < ledWidth; x++)
                    {
                        posX = (float)(fScaleRatioX * (x));
                        {
                            if (_current != null)
                            {
                                // BGRA bitmap -> RGBA Color
                                _currentColor = Color.FromArgb(_current[2], _current[1], _current[0]);
                                if (_currentColor.ToArgb() == Color.Red.ToArgb() ||
                                    _currentColor.ToArgb() == Color.Lime.ToArgb() ||
                                    _currentColor.ToArgb() == Color.Yellow.ToArgb())
                                {
                                    _graphic.FillEllipse(new SolidBrush(_currentColor), posX, posY, fScaleRatioX, fScaleRatioY);
                                }
                                else
                                {
                                    _graphic.FillEllipse(new SolidBrush(Color.Gray), posX, posY, fScaleRatioX, fScaleRatioY);
                                }
                            }
                        }
                        _current += Image.GetPixelFormatSize(_sourceBitmap.PixelFormat); ;
                    }
                }
            }

            _sourceBitmap.UnlockBits(_bmd);
            */
        }
        
    }
}
